﻿using System;
using System.Collections.Generic;
using System.Text;

namespace TLang.Ast
{
    using Values;

    public class DeclareNode : Node
    {
        private readonly Scope _propertyForm;


        public DeclareNode(Scope propertyForm, String file, int start, int end, int line, int col) : base(file, start, end, line, col)
        {
            this._propertyForm = propertyForm;
        }


        public override Value Interp(Scope s)
        {
            //mergeProperties(propsNode, s);
            return VoidValue.Void;
        }

        public static void MergeDefault(Scope properties, Scope s)
        {
            foreach (String key in properties.KeysLocal)
            {
                Object defaultValue = properties.LookupPropertyLocal(key, "default");
                if (defaultValue == null)
                {
                    continue;
                }
                else if (defaultValue is Value)
                {
                    Value existing = s.Lookup(key);
                    if (existing == null)
                    {
                        s.PutValue(key, (Value)defaultValue);
                    }
                }
                else
                {
                    throw Util.GeneralError("default value is not a value, shouldn't happen");
                }
            }
        }
        
        public static void MergeType(Scope properties, Scope s)
        {
            foreach (String key in properties.KeysLocal)
            {
                if (key.Equals(Constants.ReturnArrow))
                {
                    continue;
                }
                Object type = properties.LookupPropertyLocal(key, "type");
                if (type == null)
                {
                    continue;
                }
                else if (type is TType)
                {
                    Value existing = s.Lookup(key);
                    if (existing == null)
                    {
                        s.PutType(key, (TType)type);
                    }
                }
                else
                {
                    throw Util.GeneralError("illegal type, shouldn't happen" + type);
                }
            }
        }
        
        public static Scope EvalProperties(Scope unevaled, Scope s)
        {
            Scope evaled = new Scope();

            foreach (String field in unevaled.KeysLocal)
            {
                Map<String, Object> props = unevaled.LookupAllProps(field);
                foreach (var e in props)
                {
                    Object v = e.Value;
                    if (v is Node)
                    {
                        Value vValue = ((Node)v).Interp(s);
                        evaled.Put(field, e.Key, vValue);
                    }
                    else
                    {
                        throw Util.GeneralError("property is not a node, parser bug: " + v);
                    }
                }
            }
            return evaled;
        }

        public override String ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(Constants.ParenBegin);
            sb.Append(Constants.DeclareKeyword).Append(" ");

            foreach (String field in _propertyForm.KeysLocal)
            {
                Map<String, Object> props = _propertyForm.LookupAllProps(field);
                foreach (var e in props)
                {
                    sb.Append(" :" + e.Key + " " + e.Value);
                }
            }

            sb.Append(Constants.ParenEnd);
            return sb.ToString();
        }
    }
}
